<?php

/**
 * 框架核心辅助功能函数
 * 
 * 获取核心类实例，加载外部类库，调试相关工具等
 * 
 * @package sFramework
 */
if (!defined('BASE_PATH'))
	exit('Restricted access');

/**
 * 获取核心类的实例。
 * 
 * 如果类不存在，则实例化并存入静态变量。若之前已经
 * 实例化，则直接返回之前实例化的类。
 * 
 * @param string $class  需要获取类的名称
 * @param bool $reload   是否重新加载
 * @return	object
 */
function &load_class($class, $reload = false) {
	static $objects = array();

	if (isset($objects[$class]) && $reload == false) {
		return $objects[$class];
	}

	$name = ucfirst(strtolower($class));

	if (!class_exists($name)) {
		show_error("Unable to load class: $name");
	}


	$objects[$class] = new $name();

	return $objects[$class];
}

/**
 * 获取数据库连接对象 
 * 
 * 如果对象不存在，则实例化并存入静态变量。若之前已经
 * 实例化，则直接返回之前实例化的类。
 */
function &get_db() {
	static $instances = array();

	$config = &load_class('Config');
	$options = $config->get_item('db_config');

	$signature = md5(serialize($options));

	if (empty($instances[$signature])) {
		require_once FRAME_PATH . DS . 'database' . DS . 'database.php';

		if (!isset($options['dbdrive']) OR $options['dbdrive'] == '') {
			show_error('You have not selected a database type to connect to.');
		}

		$driver_file = FRAME_PATH . DS . 'database' . DS . 'drives' . DS . strtolower(trim($options['dbdrive'])) . '.php';

		if (!file_exists($driver_file)) {
			show_error('The database driver files dose not exist.');
		}

		require_once $driver_file;
		$driver = strtolower($options['dbdrive']) . 'Database';

		if (!class_exists($driver)) {
			show_error('The database driver you selected dose not supported.');
		}

		$instances[$signature] = new $driver($options);
	}

	return $instances[$signature];
}

/**
 * 获取指定的数据模型
 * 
 * @param $model_name
 */
function &get_model($model_name) {
	static $models = array();

	if (!isset($models[$model_name])) {
		$config = &load_class('Config');
		$model_name = strtolower($model_name);
		$model_file = BASE_PATH . DS . $config->get_item('model_folder') . DS . $model_name . '.' . $config->get_item('model_ext');

		if (!file_exists($model_file)) {
			show_error('The model files dose not exist.');
		}
		require_once $model_file;
		$model_class_name = $model_name . $config->get_item('model_class_ext');
		$models[$model_name] = new $model_class_name();
	}

	return $models[$model_name];
}

/**
 * 加载指定类库
 * 
 * @param string $filePath
 * @param string $base
 */
function import_lib($filePath, $base = null) {
	static $paths = array();
	$config = &load_class('Config');

	$keyPath = $config->get_item('libraries') ? $config->get_item('libraries') . '.' . $filePath : $filePath;

	if (!isset($paths[$keyPath])) {
		if (!$base) {
			$base = BASE_PATH;
		}

		$path = str_replace('.', DS, $keyPath);
		$file = $base . DS . $path . '.php';
		if (!file_exists($file)) {
			show_error('The files ' . $path . '.php dose not exist.');
		}
		$paths[$keyPath] = include($base . DS . $path . '.php');
	}

	return $paths[$keyPath];
}

/**
 * rdump函数别名
 * @param  $arr
 */
function dump($arr) {
	$args = func_get_args();
	call_user_func_array('rdump', $args);
}

/**
 *  格式化显示出变量
 *
 *  @author Garbin
 *  @param  any
 *  @return void
 */
function rdump($arr) {
	echo '<pre>';
	array_walk(func_get_args(), create_function('&$item,$key', 'print_r($item);'));
	echo '</pre>';
	exit();
}

/**
 *  格式化并显示出变量类型
 *
 *  @author Garbin
 *  @param  any
 *  @return void
 */
function vdump($arr) {
	echo '<pre>';
	array_walk(func_get_args(), create_function('&$item, $key', 'var_dump($item);'));
	echo '</pre>';
	exit();
}

/**
 * 显示错误信息并中断程序
 * 
 * @param array or string $message
 */
function show_error($message) {
	$message = '<li>' . implode('</li><li>', (!is_array($message)) ? array($message) : $message) . '</li>';
	echo "<p>Some Error Was Encountered :&nbsp;&nbsp;<p><ul>$message</ul>";
	exit();
}

/**
 *  返回分页信息数组
 *  <pre>
 * 	$page = array(
 * 		'total'      => '5', // 记录总数
 * 		'per_page' 	 => '2', // 每页显示记录数
 * 		'page_total' => '3', // 总页数
 * 		'cur_page'   => '2',  // 当前页码
 * 		'url'	     => 'index.php'	// 当前url
 * 		'page_links' => array( // 页面链接
 * 			1 => 'index.php?page=1',
 * 			2 => 'index.php?page=2',
 * 			3 => 'index.php?page=3'
 * 		),
 * 		'prev_link'	 => 'index.php?page=1'	// 前一页链接
 * 		'next_link'	 => 'index.php?page=3'	// 后一页链接
 * 	);
 * </pre>
 * 
 * @param int $total 数据总数
 * @param int $curr_page 当前页码
 * @param string $url 链接
 * @param int $perpage 每页显示数据条数
 * @param int $num 需要显示的页码链接数量
 *
 * @return array $page
 */
function format_page($total, $cur_page, $url = '', $perpage = 10, $num = 10,$param_name = "page") {

	$page['total'] = $total; // 总数据量
	$page['per_page'] = $perpage; // 每页显示
	$page['page_total'] = ceil($total / $perpage); // 总页数
	$cur_page > $page['page_total'] && $cur_page = $page['page_total'];
	$page['cur_page'] = $cur_page;
	$page['url'] = $url;
	
	$link_str = strpos($url,"?") ? "&" : "?";
	
	// 计算当前应该显示的页码链接范围
	$mid = ceil($num / 2) - 1;
	$mid == 0 && $mid = 1;

	if ($page['page_total'] <= $num) {
		$from = 1;
		$to = $page['page_total'];
	} else {
		$from = $cur_page <= $mid ? 1 : $cur_page - $mid + 1;
		$to = $from + $num - 1;
		$to > $page['page_total'] && $to = $page['page_total'];

		$diff = $to - $from;
		if ($diff < $num) {
			$from -= $num - $diff - 1;
			if ($from <= 0) {
				$from = 1;
			}
		}
	}
	// 生成页码链接
	$page['page_links'] = array();
	for ($i = $from; $i <= $to; $i++) {
		$page['page_links'][$i] = "$url" .$link_str. $param_name . "=$i";
	}

	// 上一页，下一页
	$page['prev_link'] = '';
	$page['next_link'] = '';
	if (($cur_page >= $from && $cur_page > 1) || ($cur_page == $page['page_total'] && $cur_page > 1)) {
		$page['prev_link'] = "$url" .$link_str. $param_name . "=" . ($cur_page - 1);
	}

	if ($cur_page <= $to && $cur_page != $page['page_total']) {
		$page['next_link'] = "$url" .$link_str. $param_name . "=" . ($cur_page + 1);
	}

	return $page;
}

/**
 * 使用数组记录中的某一值作为整个数组的索引
 * <code>
 * $test = array (0=>array('id'=5,'name'='tester'));
 * $result = specify_array_key($test,'id');
 * //$result = array (5=>array('id'=5,'name'='tester'));
 * </code>
 * @param array $data 原始数组
 * @param string $key 将使用的键名
 */
function specify_array_key($data, $key = '') {

	if (!is_array($data) || empty($key)) {
		return $data;
	}

	$result = array();
	foreach ($data as $val) {
		if (empty($val [$key]))
			return $data;
		$result [$val [$key]] = $val;
	}

	return $result;
}